package me.w70.bot.gui.rs;

import java.awt.AWTPermission;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.SocketPermission;
import java.net.URL;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.Calendar;
import java.util.HashMap;
import java.util.PropertyPermission;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import com.sun.org.apache.bcel.internal.classfile.ClassParser;

/**
 * The Rs Class Loader.
 */
public class RSLoader extends ClassLoader {
	public HashMap<String, Class<?>> classes = new HashMap<String, Class<?>>();

	JarFile jar = null;

	private CodeSource codeSource;

	private ProtectionDomain domain;

	public RSLoader() throws java.io.IOException {
		jar = downloadRunescapeJar();

	}

	private Permissions getPermissions() {
		Permissions ps = new Permissions();
		ps.add(new AWTPermission("accessEventQueue"));
		ps.add(new PropertyPermission("user.home", "read"));
		ps.add(new PropertyPermission("java.vendor", "read"));
		ps.add(new PropertyPermission("java.version", "read"));
		ps.add(new PropertyPermission("os.name", "read"));
		ps.add(new PropertyPermission("os.arch", "read"));
		ps.add(new PropertyPermission("os.version", "read"));
		ps.add(new SocketPermission("*"/* .runescape.com" */,
				"connect,resolve"));// quick fix TODO FIXME
		String uDir = System.getProperty("user.home");
		if (uDir != null) {
			uDir += "/";
		} else {
			uDir = "~/";
		}
		String[] dirs = { "c:/rscache/", "/rscache/", "c:/windows/",
				"c:/winnt/", "c:/", uDir, "/tmp/", "." };
		// If "." fails then System.getProperty("user.dir") should work
		String[] rsDirs = { ".jagex_cache_32", ".file_store_32" };
		for (String dir : dirs) {
			File f = new File(dir);
			ps.add(new FilePermission(dir, "read"));
			if (!f.exists())
				continue;
			dir = f.getPath();
			for (String rsDir : rsDirs) {
				ps.add(new FilePermission(dir + File.separator + rsDir
						+ File.separator + "-", "read"));
				ps.add(new FilePermission(dir + File.separator + rsDir
						+ File.separator + "-", "write"));
			}
		}
		Calendar.getInstance();
		// TimeZone.getDefault();//Now the default is set they don't need
		// permission
		// ps.add(new FilePermission())
		ps.setReadOnly();
		return ps;
	}

	public Class<?> findClass(String name) {
		return classes.get(name);
	}

	public Class<?> loadClass(String className) throws ClassNotFoundException,
			LinkageError {
		// System.out.println("LOADING " + className);
		Class<?> c;

		try {
			c = super.findSystemClass(className);
			classes.put(className, c);
			return c;
		} catch (ClassNotFoundException classException) {
			ZipEntry zip = jar.getEntry(className.replaceAll("\\.", "/")
					+ ".class");
			byte[] buffer;
			try {
				buffer = new ClassParser(jar.getInputStream(zip), className)
						.parse().getBytes();
			} catch (IOException e) {
				e.printStackTrace();
				Class<?> classlc = super.loadClass(className);
				classes.put(className, classlc);
				return classlc;
			}
			Class<?> cd = defineClass(className, buffer, 0, buffer.length,
					domain);
			classes.put(className, cd);
			return cd;
		}
	}

	private JarFile downloadRunescapeJar() {
		try {
			codeSource = new CodeSource(new URL("http://runescape.com/"),
					(CodeSigner[]) null);
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		domain = new ProtectionDomain(codeSource, getPermissions());
		File rJar = new File("rs.jar");

		/*
		 * if(rJar.exists()) { if(!rJar.delete()) { System.out.println("Failed
		 * to remove old runescape.jar"); return null; } }
		 */
		// long startTime = System.currentTimeMillis();
		try {
			// System.out.print("Downloading runescape.jar Method by Affix\n");
			// URLConnection jarUC;
			// jarUC = new
			// URL("http://world"+Loader.worldID+".runescape.com/runescape.jar").openConnection();
			/*
			 * JarURLConnection jarUrl = (JarURLConnection)new
			 * URL("jar:http://world"+Loader.worldID+".runescape.com/runescape.jar!/")
			 * .openConnection();
			 */
			/*
			 * DataInputStream down = new
			 * DataInputStream(jarUC.getInputStream()); PrintStream out = new
			 * PrintStream(rJar); double length = jarUC.getContentLength();
			 * double tempLength = rJar.length(); int read; byte[] buffer = new
			 * byte[5000]; while ((read = down.read(buffer)) > 0)
			 * out.write(buffer, 0, read); System.out.println("\rDownloaded
			 * runescape.jar succesfully.\n\n"); return new JarFile(rJar);
			 */
			// return jarUrl.getJarFile();
			return new JarFile(rJar);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}
